package com.budgetbears.champagneshaketitle;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.FixedStepEngine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.handler.timer.ITimerCallback;
import org.anddev.andengine.engine.handler.timer.TimerHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnAreaTouchListener;
import org.anddev.andengine.entity.scene.Scene.ITouchArea;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.scene.menu.MenuScene;
import org.anddev.andengine.entity.scene.menu.MenuScene.IOnMenuItemClickListener;
import org.anddev.andengine.entity.scene.menu.item.IMenuItem;
import org.anddev.andengine.entity.scene.menu.item.SpriteMenuItem;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.text.ChangeableText;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.graphics.Color;
import android.graphics.Typeface;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.KeyEvent;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.budgetbears.champagneshaketitle.ParallaxBackgroundY.ParallaxEntity;

public class ChampagneShakeGame extends BaseGameActivity implements SensorEventListener, IOnAreaTouchListener, IOnMenuItemClickListener {

	// ===========================================================
	// Constants
	// ===========================================================

	private static final int CAMERA_WIDTH = 480;
	private static final int CAMERA_HEIGHT = 800;

	protected static final int MENU_RESET = 2;
    protected static final int MENU_QUIT = MENU_RESET + 1;
    //Use the instance from the menu class! Don't know if this will work
    protected static final ScoreDatabase database = ChampagneShakeTitle.database;

	// ===========================================================
	// Fields
	// ===========================================================

	private AnimatedSprite animBottle;
	private AnimatedSprite animCork;
//	private Sprite cork;
	private Sprite bottle;
	private AnimatedSprite physicsCork;
	private Camera mCamera;
	private Texture mBottleTexture;
	private Texture mAnimBottleTexture;
	private Texture mCorkTexture;
	private Texture mAnimCorkTexture;
	private TextureRegion mBottleTextureRegion;
	private TiledTextureRegion mAnimBottleTextureRegion;
	private TextureRegion mCorkTextureRegion;
	private TiledTextureRegion mAnimCorkTextureRegion;
	private SensorManager sensorManager;
	private float accellerometerSpeedX;
	private float accellerometerSpeedY;
	private int bottleX, bottleY; // Sprite coordinates
	private int corkX, corkY;
	private int sensorActivity;
	private Texture mFontTexture;
	private Texture mFontTexture2;
    private Font mFont;
    private Font mFont2;
    private ChangeableText sensorText;
    private ChangeableText timerText;
    private boolean timer = true;
    private boolean fired = false;
    private boolean peak = false;
    private boolean fireDone = false;
    private boolean launch = false;
    private int height;
    //Create an enum for the current state of the game and set to TIMER
    private enum CurrentState {TIMER, SHAKE, LAUNCH, FIRED, END};
    CurrentState curState = CurrentState.TIMER;
    
    // ===========================================================
	// Background Fields
	// ===========================================================
    
    private ParallaxBackgroundY pBack;
    private Texture pBackgroundTexture;
    private TextureRegion pBackgroundBack;
    private TextureRegion pBackgroundMid;
    private TextureRegion pBackgroundFront;
    private TextureRegion pBackgroundExtra;
    
    // ===========================================================
	// Background Fields
	// ===========================================================
    
    
    //Timer handler
    TimerHandler countdownTimerHandler;
    
    //Scenes, one for game, one for menu
    protected Scene mMainScene;
    protected MenuScene mMenuScene;
    protected Scene mTimerScene;

   //textures and regions for menu items
    private Texture mMenuTexture;
    protected TextureRegion mMenuResetTextureRegion;
    protected TextureRegion mMenuQuitTextureRegion;
    
    private PhysicsWorld mPhysicsWorld;
    private Body body;

    private float mGravityY = -9;

    private final Vector2 mTempVector = new Vector2();
    

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	public Engine onLoadEngine() {
		this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		return new FixedStepEngine(new EngineOptions(true, ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera), 60);
	}

	@Override
	public void onLoadResources() {
		
		//Create texture and texture regions for parallax background
		this.pBackgroundTexture = new Texture(2048, 2048, TextureOptions.DEFAULT);
        this.pBackgroundBack = TextureRegionFactory.createFromAsset(this.pBackgroundTexture, this, "gfx/bkg1.png", 0, 0);
        this.pBackgroundMid = TextureRegionFactory.createFromAsset(this.pBackgroundTexture, this, "gfx/bkg2.png", 481, 0);
        this.pBackgroundFront = TextureRegionFactory.createFromAsset(this.pBackgroundTexture, this, "gfx/bkg3.png", 961, 0);
        //this.pBackgroundExtra = TextureRegionFactory.createFromAsset(this.pBackgroundTexture, this, "gfx/bkg4.png", 1441, 0);
        
        this.mEngine.getTextureManager().loadTexture(this.pBackgroundTexture);
        
		//Create Texture for Font and Font
		this.mFontTexture = new Texture(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFont = new Font(this.mFontTexture, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 32, true, Color.BLACK);
		this.mFontTexture2 = new Texture(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFont2 = new Font(this.mFontTexture2, Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC), 80, true, Color.BLACK);
        

        //Load Font texture and font into engine
        this.mEngine.getTextureManager().loadTexture(this.mFontTexture);
        this.mEngine.getTextureManager().loadTexture(this.mFontTexture2);
        this.mEngine.getFontManager().loadFont(this.mFont);
        this.mEngine.getFontManager().loadFont(this.mFont2);

        //Load bottle Texture and texture region from resource
		this.mBottleTexture = new Texture(128, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mBottleTextureRegion = TextureRegionFactory.createFromAsset(this.mBottleTexture, this, "gfx/bottlerender.png", 0, 0);
		
		//Load bottle Texture and texture region from resource
		this.mAnimBottleTexture = new Texture(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mAnimBottleTextureRegion = TextureRegionFactory.createTiledFromAsset(this.mAnimBottleTexture, this, "gfx/BottleSpriteSheet.png", 0, 0, 4, 1);
		
		//Load cork Texture and texture region from resource
		this.mCorkTexture = new Texture(32, 64, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mCorkTextureRegion = TextureRegionFactory.createFromAsset(this.mCorkTexture, this, "gfx/cork.png", 0, 0);
		
		//Load cork Texture and texture region from resource
		this.mAnimCorkTexture = new Texture(512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mAnimCorkTextureRegion = TextureRegionFactory.createTiledFromAsset(this.mAnimCorkTexture, this, "gfx/corkspritesmall.png", 0, 0, 8, 2);

		//Add Cork and Bottle textures to engine texture manager
		this.mEngine.getTextureManager().loadTexture(this.mBottleTexture);
		this.mEngine.getTextureManager().loadTexture(this.mAnimBottleTexture);
		this.mEngine.getTextureManager().loadTexture(this.mCorkTexture);
		this.mEngine.getTextureManager().loadTexture(this.mAnimCorkTexture);
		
		//Load menu textures
		this.mMenuTexture = new Texture(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.mMenuResetTextureRegion = TextureRegionFactory.createFromAsset(this.mMenuTexture, this, "gfx/menu_reset.png", 0, 0);
        this.mMenuQuitTextureRegion = TextureRegionFactory.createFromAsset(this.mMenuTexture, this, "gfx/menu_quit.png", 0, 50);
        this.mEngine.getTextureManager().loadTexture(this.mMenuTexture);
/*       
        //How to test value of enum
        if (curState == CurrentState.TIMER);
        if (curState.toString() == "TIMER");
        if (curState.equals(0));
        if (curState.ordinal() == 0);
        
        //How to set value of enum
        curState = CurrentState.FIRED;
*/
	}

	@Override
	public Scene onLoadScene() {

		this.mEngine.registerUpdateHandler(new FPSLogger());
		sensorManager = (SensorManager) this.getSystemService(ChampagneShakeGame.SENSOR_SERVICE);
		sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
		
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
        
        this.createTimerScene();
        this.createMenuScene();
        this.createMainScene();
		
		this.mEngine.registerUpdateHandler(new IUpdateHandler() {
            public void onUpdate(float pSecondsElapsed) {
            	
            	switch(curState) {
            	case TIMER:
            		//TODO
            		break;
            	case SHAKE:
            		//TODO
            		break;
            	case LAUNCH:
            		//TODO
            		break;
            	case FIRED:
            		//TODO
            		break;
            	case END:
            		//TODO
            		break;
            	}
            	
            	if (fired == true && fireDone == false){
            		//Add a physics object using the cork sprite
            		physicsCork = new AnimatedSprite(corkX, corkY, mAnimCorkTextureRegion);
            		physicsCork.setScale(1.5f, 1.0f);
            		mMainScene.attachChild(physicsCork);
            		final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(0.5f, 0.5f, 0.3f);
            		body = PhysicsFactory.createBoxBody(mPhysicsWorld, physicsCork, BodyType.DynamicBody, objectFixtureDef);
            		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsCork, body, true, true));
            		
            		//DIRTILY!! Add another physics object to collide with
            		Sprite physicsObj = new Sprite(CAMERA_WIDTH/2 +mCorkTextureRegion.getWidth()/2, CAMERA_HEIGHT -mCorkTextureRegion.getHeight(), mCorkTextureRegion);
            		physicsObj.setScale(1.5f, 1.0f);
            		mMainScene.attachChild(physicsObj);
            		Body newBody = PhysicsFactory.createBoxBody(mPhysicsWorld, physicsObj, BodyType.DynamicBody, objectFixtureDef);
            		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsObj, newBody, true, true));
            		
            		Sprite physicsObj2 = new Sprite(CAMERA_WIDTH/2 -mCorkTextureRegion.getWidth()/2, CAMERA_HEIGHT -mCorkTextureRegion.getHeight(), mCorkTextureRegion);
            		physicsObj2.setScale(1.5f, 1.0f);
            		mMainScene.attachChild(physicsObj2);
            		Body newBody2 = PhysicsFactory.createBoxBody(mPhysicsWorld, physicsObj2, BodyType.DynamicBody, objectFixtureDef);
            		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsObj2, newBody2, true, true));
            		
            		Sprite physicsObj3 = new Sprite(CAMERA_WIDTH/2, CAMERA_HEIGHT -(mCorkTextureRegion.getHeight())*2, mCorkTextureRegion);
            		physicsObj3.setScale(1.5f, 1.0f);
            		mMainScene.attachChild(physicsObj3);
            		Body newBody3 = PhysicsFactory.createBoxBody(mPhysicsWorld, physicsObj3, BodyType.DynamicBody, objectFixtureDef);
            		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsObj3, newBody3, true, true));
            		
            		Sprite physicsObj4 = new Sprite(CAMERA_WIDTH/2, CAMERA_HEIGHT -(mCorkTextureRegion.getHeight())*3, mCorkTextureRegion);
            		physicsObj4.setScale(1.5f, 1.0f);
            		mMainScene.attachChild(physicsObj4);
            		Body newBody4 = PhysicsFactory.createBoxBody(mPhysicsWorld, physicsObj4, BodyType.DynamicBody, objectFixtureDef);
            		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsObj4, newBody4, true, true));
            		
            		//get 1000th of sensor activity variable as it is too big.
            		float movement = sensorActivity * 0.001f;
	    			body.setLinearVelocity(mTempVector.set(0, (mGravityY * (movement))));
	    			mCamera.setChaseEntity(physicsCork);
	    			//physicsCork.animate(50);
	    			
            		//Set the parallax background to move
            		//pBack.setParallaxValue(-Math.abs(body.getLinearVelocity().y));
	    			fireDone = true;
            	}
            	
            	if (fired == true) {
            		pBack.setParallaxValue(-mCamera.getCenterY()/10);
            	}
            	
            	//Test if the cork is fired and if it is moving to animate it TODO - maybe add relative speed for animation
            	if (fired == true && body.getLinearVelocity().y < 0.0f) {
            		physicsCork.animate(50);
            	}
            	
            	if (timer == true && countdownTimerHandler.getTimerSecondsElapsed() > 0.00f) {
            		//set Text to countdown
  	              	timerText.setPosition(mCamera.getCenterX() - timerText.getBaseWidth()/2, mCamera.getCenterY() - timerText.getBaseHeight()/2);
  	              	timerText.setText("" + ( 6 - countdownTimerHandler.getTimerSecondsElapsed()));
            	}
            	//Test if cork has fired
            	if (fired == false && timer == false) {
            		if(countdownTimerHandler.getTimerSecondsElapsed() < 6.00f) {
            			//If not update bottle and cork position on sensor movement
            			updateBottlePosition();
            			updateCorkPosition();
            		} else {
            			sensorText.setText("TAP TO LAUNCH!!!");
            			launch = true;
            		}
            		//Which will be every update after anim has finished!
                    //Only want this code to run once (check if the bottle anim is on penultimate frame)
/*
                    if (animBottle.getCurrentTileIndex() == 3) {
                    	
    	    			//fired = true;
                    }
*/                    
            	} else if (timer == false){
            		//if fired update physics cork using sensor X movement - DOESN'T WORK TODO Fix!
            		updatePhysicsCorkPosition();
            		//Display the height when cork stops rising, removing camera chase removed!, 
            		if(body.getLinearVelocity().y >= 0.0f && peak == false) {
            			//mCamera.setChaseShape(null);
            			body.setAngularVelocity(2);
            			sensorText.setPosition(mCamera.getCenterX() - CAMERA_WIDTH/3, mCamera.getCenterY() - 300);
            			//This is the actual height of the cork sprite, has to be abs as top of initial screen is 0 and bottom is 800
            			height = (int)Math.abs(physicsCork.getY());
            			sensorText.setText("Height: " + height + " metres!");
            			peak = true;
            		}
            	}
            	if(peak == true) {
            		//InsertIntoDatabase(height);
            		sensorText.setPosition(mCamera.getCenterX() - CAMERA_WIDTH/3, mCamera.getCenterY() - 300);
            		sensorText.setText("Height: " + height + " metres!");
            		bottle.setPosition((CAMERA_WIDTH - mBottleTextureRegion.getWidth()) / 2, (CAMERA_HEIGHT - mBottleTextureRegion.getHeight()) / 2);
            		bottle.setVisible(false);
            		//TODO add a few seconds of paused cork
            		//body.setAwake(false);
            		if(physicsCork.getY() >= 0) {
            			mCamera.setChaseEntity(bottle);
            		}
            	}

            	
            }
            public void reset() {
                // TODO Auto-generated method stub
            }
        });
		
		createCountdownTimeHandler();
		return this.mTimerScene;
	}

	
	@Override
	public void onLoadComplete() {
	}
	
	public void onSensorChanged(SensorEvent event) {
	        synchronized (this) {
	            switch (event.sensor.getType()) {
	                case Sensor.TYPE_ACCELEROMETER:
	                    accellerometerSpeedX = event.values[0];
	                    accellerometerSpeedY = event.values[1];
	                    break;
	            }
	        }
	    }
	    public void onAccuracyChanged(Sensor sensor, int accuracy) {
	        //
	    }
	    
	    //Inherited method for dealing with OnAreaTouchedListener event
	    public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final ITouchArea pTouchArea,final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
	    	if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN && fired == false && launch == true) {
	    		
	    		//fire cork when bottle is touched
	    		animCork.setVisible(false);
	    		//animBottle.animate(100, 0);
	    		fired = true;
	    		
	    		return true;
                }
	    	return false;
        }
	    
	    //KeyDown event override for menu choices
	    @Override
        public boolean onKeyDown(final int pKeyCode, final KeyEvent pEvent) {
                if(pKeyCode == KeyEvent.KEYCODE_MENU && pEvent.getAction() == KeyEvent.ACTION_DOWN) {
                        if(this.mEngine.isRunning()) {
                        	//add child scene
                        	this.mMainScene.setChildScene(this.mMenuScene, false, true, true);
                        	sensorManager.unregisterListener(ChampagneShakeGame.this);
                            mEngine.stop();
                        } else {
                            //remove menu
                        	this.mMainScene.clearChildScene();
                        	sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
                            mEngine.start();
                        }
                        return true;
                } else {
                        return super.onKeyDown(pKeyCode, pEvent);
                }
        }
	    
	    //Menu item clicked override for menu choices
	    @Override
        public boolean onMenuItemClicked(final MenuScene pMenuScene, final IMenuItem pMenuItem, final float pMenuItemLocalX, final float pMenuItemLocalY) {
                switch(pMenuItem.getID()) {
                        case MENU_RESET:
                                /* Restart the animation. */
                                this.mMainScene.reset();
                                /* Remove the menu and reset it. */
                                this.mMainScene.clearChildScene();
                                this.mMenuScene.reset();
                                return true;
                        case MENU_QUIT:
                                /* End Activity. */
                                this.finish();
                                return true;
                        default:
                                return false;
                }
        }


	// ===========================================================
	// Methods
	// ===========================================================

	    private void updateBottlePosition() {
	            if ((accellerometerSpeedX != 0) || (accellerometerSpeedY != 0)) {
	                // Set the Boundary limits
	                int topLimit = 0;
	                int leftLimit = CAMERA_WIDTH/4;
	                int rightLimit = ((CAMERA_WIDTH/4)*3) - (int)bottle.getWidth();
	                int bottomLimit = CAMERA_HEIGHT - (int)bottle.getHeight();
	                // Calculate New X,Y Coordinates within Limits
	                if (bottleX >= leftLimit) bottleX -= accellerometerSpeedX; else bottleX = leftLimit;
	                if (bottleX <= rightLimit) bottleX -= accellerometerSpeedX; else bottleX = rightLimit;
	                if (bottleY >= topLimit) bottleY += accellerometerSpeedY; else bottleY = topLimit;
	                if (bottleY <= bottomLimit) bottleY += accellerometerSpeedY; else bottleY = bottomLimit;
	                // Double Check That New X,Y Coordinates are within Limits
	                if (bottleX < leftLimit)      bottleX = leftLimit;
	                else if (bottleX > rightLimit) bottleX = rightLimit;
	                if (bottleY < topLimit)      bottleY = topLimit;
	                else if (bottleY > bottomLimit) bottleY = bottomLimit;
	                bottle.setPosition(bottleX, bottleY);
	                //Calculate how much the sensors have moved and store in a variable
	                sensorActivity += Math.abs(accellerometerSpeedX) + Math.abs(accellerometerSpeedY);
	                //update the text for debug purposes
	                sensorText.setText("Sensor activity: " + sensorActivity);
	            }
	        }
	    
	    private void updateCorkPosition() {
	    	corkX = (bottleX + (this.mBottleTextureRegion.getWidth() / 2) - this.mCorkTextureRegion.getWidth() / 2) ;
	    	corkY = bottleY;
	    	animCork.setPosition(corkX, corkY);
	    }
	    
	    //Attempted method to allow X axis movement of cork while in the air by tilting TODO make work! below obviously resets Y velocity as well
	    private void updatePhysicsCorkPosition() {
	    	//if (accellerometerSpeedX != 0)
	    	//body.setLinearVelocity(mTempVector.set(accellerometerSpeedX, 0));
	    }
	    
	    protected void createTimerScene() {
	    	this.mTimerScene = new Scene(1);
	    	mTimerScene.setBackground(new ColorBackground(0.5f, 0.6f, 0.8f));
	    	
	    	timerText = new ChangeableText(CAMERA_WIDTH/2, CAMERA_HEIGHT/2, this.mFont2, "", "X".length());
			mTimerScene.attachChild(timerText);
	    }
	   
	    //Method to create the menu scene
	    protected void createMenuScene() {
            this.mMenuScene = new MenuScene(this.mCamera);

            final SpriteMenuItem resetMenuItem = new SpriteMenuItem(MENU_RESET, this.mMenuResetTextureRegion);
            resetMenuItem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
            this.mMenuScene.addMenuItem(resetMenuItem);
            
            final SpriteMenuItem quitMenuItem = new SpriteMenuItem(MENU_QUIT, this.mMenuQuitTextureRegion);
            quitMenuItem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
            this.mMenuScene.addMenuItem(quitMenuItem);
            
            this.mMenuScene.buildAnimations();

            this.mMenuScene.setBackgroundEnabled(false);

            this.mMenuScene.setOnMenuItemClickListener(this);
    }
	    
	    protected void createMainScene() {
	    	this.mMainScene = new Scene(1);
	    	
	    	//create ground for the cork to land on - do it first so its hidden behind the rest of the graphics
			final Shape ground = new Rectangle(0, CAMERA_HEIGHT, CAMERA_WIDTH, 2);
			final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);
	        PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
	        mMainScene.attachChild(ground);
	        
	        //mMainScene.setBackground(new ColorBackground(0.5f, 0.6f, 0.8f));
	    	
	    	pBack = new ParallaxBackgroundY(0, 0, 0);
	    	pBack.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, 0, this.pBackgroundBack)));
	    	//pBack.attachParallaxEntity(new ParallaxEntity(0.5f, new Sprite(0, -800, this.pBackgroundExtra)));
	    	pBack.attachParallaxEntity(new ParallaxEntity(1.0f, new Sprite(0, 0, this.pBackgroundMid)));
	    	pBack.attachParallaxEntity(new ParallaxEntity(7.0f, new Sprite(0, 0, this.pBackgroundFront)));
	    	
	    	
	    	mMainScene.setBackground(pBack);

			/* Calculate the coordinates for the face, so its centred on the camera. */
			bottleX = (CAMERA_WIDTH - this.mBottleTextureRegion.getWidth()) / 2;
			bottleY = (CAMERA_HEIGHT - this.mBottleTextureRegion.getHeight()) / 2;
			corkX = (bottleX + (this.mBottleTextureRegion.getWidth() / 2) - this.mCorkTextureRegion.getWidth() / 2) ;
	    	corkY = bottleY;
	/*
			//Add a physics object using the cork sprite
			final Body body;
			physicsCork = new Sprite(corkX, corkY, this.mCorkTextureRegion);
			physicsCork.setScale(1.5f, 1.0f);
			final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
			body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, physicsCork, BodyType.DynamicBody, objectFixtureDef);
			this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(physicsCork, body, true, true, false, false));
			
			scene.getTopLayer().addEntity(physicsCork);
			physicsCork.setVisible(false);
		
			//Add a Sprite from the cork
			cork = new Sprite(corkX, corkY, this.mCorkTextureRegion);
			cork.setScale(1.5f, 1.0f);
			mMainScene.getTopLayer().addEntity(cork);
		
			// Create the bottle and add it to the scene. 
			bottle = new Sprite(bottleX, bottleY, this.mBottleTextureRegion);
			bottle.setScale(1);
			scene.getTopLayer().addEntity(bottle);
	*/
	    	
	    	//create cork animated sprite
			animCork = new AnimatedSprite(corkX, corkY, this.mAnimCorkTextureRegion);
			animCork.setScale(1.5f, 1f);
			mMainScene.attachChild(animCork);
			
	    	// Create the bottle and add it to the scene. 
			bottle = new Sprite(bottleX, bottleY, this.mBottleTextureRegion);
			bottle.setScale(1, 0.85f);
			mMainScene.attachChild(bottle);

/*			
			//Create animated bottle sprite
			animBottle = new AnimatedSprite(bottleX, bottleY, this.mAnimBottleTextureRegion);
			animBottle.setScale(1);
			mMainScene.attachChild(animBottle);
*/			
			sensorText = new ChangeableText(100, 160, this.mFont, "SHAKE!", "Sensor activity: XXXXX".length());
			mMainScene.attachChild(sensorText);
			
			//Register the bottle sprite as a touchable area and set scene as a listener for touch event
			mMainScene.registerTouchArea(bottle);
			mMainScene.setOnAreaTouchListener(this);
			
			mMainScene.registerUpdateHandler(this.mPhysicsWorld);
	    }
	   
	      //Creates a Timer Handler used to countdown
	       
	      private void createCountdownTimeHandler()
	      {
	              this.getEngine().registerUpdateHandler(countdownTimerHandler = new TimerHandler(6.0f, new ITimerCallback()
	              { 
	                  @Override
	                  public void onTimePassed(final TimerHandler pTimerHandler)
	                  {
	                	  //Code for dealing with enum values
	                	  if (curState == CurrentState.TIMER) {
	                		  //TODO
	                	  }
	                	  //Start the shaking, only once as this timer is reused for shaking!
	                	  if (timer == true) {
	                		  mEngine.setScene(mMainScene);
	                		  countdownTimerHandler.reset();
	                	  }
	                	  //sensorText.setPosition(mCamera.getCenterX() - CAMERA_WIDTH/4, mCamera.getCenterY());
	                	  //sensorText.setText("BOOM: " + pTimerHandler.getTimerSeconds() + " " + count);
	                	  timer = false;
	                  }
	              }));
	      }

/*	    
	    //Method to insert high score into database
	    public void InsertIntoDatabase() {
	    	//database = new ScoreDatabase(ChampagneShakeGame.this);
    		SQLiteDatabase db = database.getWritableDatabase();
    		//TODO - Do Stuff
	    }
*/	    
	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

}